package com.hxrfid.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.hxrfid.common.core.domain.BaseEntity;
import com.hxrfid.common.core.domain.PageQuery;
import com.hxrfid.common.core.domain.entity.SysTemplate;
import com.hxrfid.common.core.domain.entity.SysTenant;
import com.hxrfid.common.core.page.TableDataInfo;
import com.hxrfid.common.exception.ServiceException;
import com.hxrfid.common.utils.StreamUtils;
import com.hxrfid.common.utils.StringUtils;
import com.hxrfid.system.domain.SysRoleMenu;
import com.hxrfid.system.domain.SysTempMenu;
import com.hxrfid.system.domain.bo.SysTemplateBo;
import com.hxrfid.system.domain.vo.SysTemplateVo;
import com.hxrfid.system.mapper.SysRoleMenuMapper;
import com.hxrfid.system.mapper.SysTempMenuMapper;
import com.hxrfid.system.mapper.SysTemplateMapper;
import com.hxrfid.system.mapper.SysTenantMapper;
import com.hxrfid.system.service.ISysTemplateService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 权限模板Service业务层处理
 *
 * @author ruoyi
 * @date 2022-11-08
 */
@RequiredArgsConstructor
@Service
public class SysTemplateServiceImpl implements ISysTemplateService {

    private final SysTemplateMapper baseMapper;

    private final SysTempMenuMapper sysTempMenuMapper;

    private final SysTenantMapper sysTenantMapper;

    private final SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 查询权限模板
     */
    @Override
    public SysTemplateVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询权限模板列表
     */
    @Override
    public TableDataInfo<SysTemplateVo> queryPageList(SysTemplateBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysTemplate> lqw = buildQueryWrapper(bo);
        Page<SysTemplateVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询权限模板列表
     */
    @Override
    public List<SysTemplateVo> queryList(SysTemplateBo bo) {
        LambdaQueryWrapper<SysTemplate> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysTemplate> buildQueryWrapper(SysTemplateBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysTemplate> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), SysTemplate::getName, bo.getName());
        lqw.like(StringUtils.isNotBlank(bo.getRemark()), SysTemplate::getRemark, bo.getRemark());
        lqw.orderByDesc(BaseEntity::getCreateTime);
        return lqw;
    }

    /**
     * 新增权限模板
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(SysTemplateBo bo) {
        SysTemplate add = BeanUtil.toBean(bo, SysTemplate.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            // 重置模板对应的菜单
            resetSysTempMenus(add.getId(), bo.getMenuIds());
        }
        return flag;
    }

    /**
     * 修改权限模板
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(SysTemplateBo bo) {
        SysTemplate update = BeanUtil.toBean(bo, SysTemplate.class);
        validEntityBeforeSave(update);
        // 重置模板对应的菜单
        resetSysTempMenus(update.getId(), bo.getMenuIds());
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysTemplate entity){
        //TODO 做一些数据校验,如唯一约束
        SysTemplate sysTemplate = baseMapper.selectOne(new LambdaQueryWrapper<SysTemplate>()
            .ne(null != entity.getId(), SysTemplate::getId, entity.getId())
            .eq(SysTemplate::getName, entity.getName()));
        if (null != sysTemplate) {
            throw new ServiceException("名称重复，请检查。");
        }
    }

    /**
     * 批量删除权限模板
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            for (Long tempId : ids) {
                checkDeleteTemp(tempId);
            }
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 重置模板对应的菜单
     * @param tempId 模板ID
     */
    private void resetSysTempMenus(Long tempId, List<Long> menuIds) {
        LambdaQueryWrapper<SysTempMenu> queryWrapper = Wrappers.<SysTempMenu>query().lambda().eq(SysTempMenu::getTempId, tempId);
        // 查询旧数据
        List<SysTempMenu> oldTempMenuList = sysTempMenuMapper.selectList(queryWrapper);
        if(!CollectionUtil.isEmpty(menuIds)){
            // 获取删除的菜单ID
            List<Long> delMenuIdList = oldTempMenuList.stream().map(SysTempMenu::getMenuId)
                .filter(l -> !menuIds.contains(l)).collect(Collectors.toList());
            // 删除角色里对应的菜单
            delTenantRoleMenu(tempId, delMenuIdList);
        }
        // 删除旧数据
        sysTempMenuMapper.delete(queryWrapper);
        if (CollectionUtil.isNotEmpty(menuIds)) {
            // 新增新数据
            List<SysTempMenu> collect = StreamUtils.toList(menuIds, menuId -> {
                SysTempMenu sysTempMenu = new SysTempMenu();
                sysTempMenu.setMenuId(menuId);
                sysTempMenu.setTempId(tempId);
                return sysTempMenu;
            });

            sysTempMenuMapper.insertBatch(collect);
        }
    }

    /**
     * 删除租户角色菜单中对应的菜单
     *
     * @param delMenuIdList
     * @param tempId
     */
    private void delTenantRoleMenu(Long tempId, List<Long> delMenuIdList) {
        // 删除菜单为空则直接返回
        if (CollectionUtil.isEmpty(delMenuIdList)) {
            return;
        }
        // 查询模板关联角色菜单
        List<SysRoleMenu> sysRoleMenuList = sysRoleMenuMapper.selectByTempIdAndMenuId(tempId, delMenuIdList);
        if (CollectionUtil.isEmpty(sysRoleMenuList)) {
            return;
        }
        // 批量删除角色菜单
        LambdaQueryWrapper<SysRoleMenu> query = Wrappers.<SysRoleMenu>query().lambda();
        List<List<SysRoleMenu>> partition = Lists.partition(sysRoleMenuList, 100);
        partition.forEach(list -> {
            query.clear();
            list.forEach(item -> query.or(lambda -> lambda.eq(SysRoleMenu::getMenuId, item.getMenuId()).eq(SysRoleMenu::getRoleId, item.getRoleId())));
            sysRoleMenuMapper.delete(query);
        });
    }

    /**
     * 删除模板校验
     * @param tempId 模板ID
     */
    private void checkDeleteTemp(Long tempId) {
        Wrapper<SysTenant> queryWrapper = Wrappers.<SysTenant>query().lambda().eq(SysTenant::getTempId, tempId);
        Long count = sysTenantMapper.selectCount(queryWrapper);
        if (null != count && count > 0) {
            SysTemplate sysTemplate = baseMapper.selectById(tempId);
            throw new ServiceException(sysTemplate.getName() + "下存在租户，请重新分配模板后再尝试删除");
        } else {
            resetSysTempMenus(tempId, null);
        }
    }

}
